#include "ZtaskHelper.h"
#include "mfAddFuncCalcTask.h"


bool XTaskHelper::CalcMainField()
{
	//create layer
	ConductiveLayer l;
	l.H = 50000;
	l.Sigma = 1;


	//calc field
	XTaskHelper xhelper;
	mfAddFuncCalcTask xtask;
	const double firstt = 1e-15;
	const double timecoef = 1.01;
	const int lcount = 3500;


	xhelper.Init(&l, 1);
	//float s = 1e-20*(1-pow(1.01, 4500.0))/(1-1.01);
	if(!xtask.Init(&l, 1, timecoef, firstt, lcount, 1, &xhelper, false))  return false;
	if(!xtask.Solve()) return false;


	feSimple1dMeshFunction::DiffDtOperation ddtop;
	feSimple1dMeshFunction::DiffDxOperation ddxop;

	//save
	if(!ddtop(xtask.GetFunc())->SaveToFile(MF_FILENAME_XDUDT, MF_FILENAME_MESH)) return false;
	if(!xtask.GetFunc()->SaveToFile(MF_FILENAME_XU, MF_FILENAME_MESH)) return false;

	return true;
}


//---------------------------------------------------------------------------------------------------------------------------------------
feBordCond ** XTaskHelper::GetBcs( bool iMainFieldCalc, int &oBcNum )
{
	UpBc = feFirstBordCond1d(0, 0);
	DownBc = feFirstBordCond1d(Mesh->NodesCount()-1, 0);
	Bcs[0] = &UpBc;
	Bcs[1] = &DownBc;

	oBcNum = 2;
	return &Bcs[0];
}


//---------------------------------------------------------------------------------------------------------------------------------------
feVector * XTaskHelper::GetX0( bool iMainFieldCalc )
{
	//set zero
	if(X0.GetSize() != Mesh->NodesCount())
	{
		X0.Free();
		X0.Allocate(Mesh->NodesCount());
	}

		
	//create border condition
	feBordCond *bc[2];	
	feFirstBordCond1d bc0(Mesh->NodesCount()-1, 0);
	feFirstBordCond1d bc1(0, iMainFieldCalc == true ? 0 : 1);
	bc[0] = &bc1;
	bc[1] = &bc0;		


	//allocate X0
	X0.Allocate(Mesh->NodesCount());


	//create solver
	fe1dParabolicTask task;
	if(!task.Init(Mesh, bc, 2, &X0, 1,  1, 1))
		return 0;


	//solve stationary
	if(!task.SolveStationary(&X0)) return 0;

	return &X0;
}


//---------------------------------------------------------------------------------------------------------------------------------------
double XTaskHelper::GetScaleSigma( int iLayerNum )
{
	return 1/Layers[iLayerNum].Sigma;
}


//---------------------------------------------------------------------------------------------------------------------------------------
void XTaskHelper::Init( ConductiveLayer *iLayers, double iM )
{
	//DownBcVec = iDownVec;
	M = iM;
	Layers = iLayers;
}


//---------------------------------------------------------------------------------------------------------------------------------------
feMeshFunction * XTaskHelper::GetMfUFunction()
{
	return MfUFunction;
}


//---------------------------------------------------------------------------------------------------------------------------------------
feMeshFunction * XTaskHelper::GetMfDuDtFunction()
{
	return MfDuDtFunction;
}


//---------------------------------------------------------------------------------------------------------------------------------------
double XTaskHelper::GetScaleFCoeff(int iLayerNum, double iSigma0)
{
	return (1.0/iSigma0 - 1.0/Layers[iLayerNum].Sigma);
}


//---------------------------------------------------------------------------------------------------------------------------------------
bool XTaskHelper::Load()
{
	if(MfMesh.Empty())
	{
		MfMesh = new mfMesh();
		if(!MfMesh->LoadFromFile(MF_FILENAME_MESH))
			return false;
	}

	if(MfUFunction.Empty())
	{
		MfUFunction = new feSimple1dMeshFunction(this->MfMesh);
		if(!MfUFunction->LoadFromFile(MF_FILENAME_XU)) return false;
	}

	if(MfDuDtFunction.Empty())
	{
		MfDuDtFunction = new feSimple1dMeshFunction(this->MfMesh);
		if(!MfDuDtFunction->LoadFromFile(MF_FILENAME_XDUDT)) return false;
	}

	return true;
}


//---------------------------------------------------------------------------------------------------------------------------------------
//ZtaskHelper
//---------------------------------------------------------------------------------------------------------------------------------------
bool ZTaskHelper::CalcMainField()
{
	//create layer
	ConductiveLayer l;
	l.H = 50000;
	l.Sigma = 1;


	//calc field
	ZTaskHelper zhelper;
	mfAddFuncCalcTask ztask;
	const double firstt = 1e-15;
	const double timecoef = 1.005;
	const int lcount = 7000;


	zhelper.Init(&l, 1);
	//float s = 1e-20*(1-pow(1.01, 4500.0))/(1-1.01);
	if(!ztask.Init(&l, 1, timecoef, firstt, lcount, 1, &zhelper, false))  return false;
	if(!ztask.Solve()) return false;


	feSimple1dMeshFunction::DiffDtOperation difop;
	//	feSimple1dMeshFunction::IntDtOperation intop;


	//save
	if(!difop(ztask.GetFunc())->SaveToFile(MF_FILENAME_ZDUDT, MF_FILENAME_MESH)) return false;
	if(!ztask.GetFunc()->SaveToFile(MF_FILENAME_ZU, MF_FILENAME_MESH)) return false;

	return true;
}


//---------------------------------------------------------------------------------------------------------------------------------------
feBordCond ** ZTaskHelper::GetBcs( bool iMainFieldCalc, int &oBcNum )
{
	UpBc = feThirdBordCond1d(0, M, 0);		
	DownBc = feThirdBordCond1d(Mesh->NodesCount()-1, M, 0);	
	Bcs[0] = &UpBc;
	Bcs[1] = &DownBc;
	oBcNum = 2;
	return &Bcs[0];
}


//---------------------------------------------------------------------------------------------------------------------------------------
feVector * ZTaskHelper::GetX0( bool iMainFieldCalc )
{
	if(!iMainFieldCalc)
	{
		//create border condition
		feBordCond *bc[2];	
		feThirdBordCond1d bc0(Mesh->NodesCount()-1, M, 0);
		feFirstBordCond1d bc1(0, 1);
		bc[0] = &bc0;
		bc[1] = &bc1;


		//allocate X0
		X0.Allocate(Mesh->NodesCount());


		//create solver
		fe1dParabolicTask task;
		if(!task.Init(Mesh, bc, 2, &X0, 1, 1, 1))
			return 0;


		//solve stationary
		if(!task.SolveStationary(&X0))
			return 0;
	}
	else
	{
		//set zero
		if(X0.GetSize() != Mesh->NodesCount())
		{
			X0.Free();
			X0.Allocate(Mesh->NodesCount());
		}

		ZeroMemory(&X0.Data[0], X0.GetSize()*sizeof(X0.Data[0]));
	}

	return &X0;
}


//---------------------------------------------------------------------------------------------------------------------------------------
void ZTaskHelper::Init( ConductiveLayer *iLayers, double iM )
{
	M = iM; 
	Layers = iLayers;
}


//---------------------------------------------------------------------------------------------------------------------------------------
bool ZTaskHelper::Load()
{
	//load mesh
	if(MfMesh.Empty())
	{
		MfMesh = new mfMesh();
		if(!MfMesh->LoadFromFile(MF_FILENAME_MESH))
			return false;
	}

	if(MfUFunction.Empty())
	{
		MfUFunction = new feSimple1dMeshFunction(this->MfMesh);
		if(!MfUFunction->LoadFromFile(MF_FILENAME_ZU)) return false;
	}

	if(MfDuDtFunction.Empty())
	{
		MfDuDtFunction = new feSimple1dMeshFunction(this->MfMesh);
		if(!MfDuDtFunction->LoadFromFile(MF_FILENAME_ZDUDT)) return false;
	}
	return true;
}


//---------------------------------------------------------------------------------------------------------------------------------------
feMeshFunction * ZTaskHelper::GetMfUFunction()
{
	return MfUFunction;
}


//---------------------------------------------------------------------------------------------------------------------------------------
feMeshFunction * ZTaskHelper::GetMfDuDtFunction()
{
	return MfDuDtFunction;
}


//---------------------------------------------------------------------------------------------------------------------------------------
double ZTaskHelper::GetScaleFCoeff(int iLayerNum, double iSigma0)
{
	return -MU0*(Layers[iLayerNum].Sigma-iSigma0)*M*M/iSigma0;
}